/*
 * SimpleHierarchyJDBMHTree.java
 *
 * Created on October 25, 2007, 11:12 AM
 *
 */
package OLDSTUFF;

// import HierarchyPackage.*;
import OLDSTUFF.ClassifiedDataSetPackage.ClassifiedDataSet;
import OLDSTUFF.DataSetPackage.View;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import jdbm.RecordManager;
import jdbm.RecordManagerFactory;
import jdbm.RecordManagerOptions;
import jdbm.helper.FastIterator;
import jdbm.htree.HTree;

/*
 * @author Martin Haulrich
 */
/**
 * Hierarchy-class for simple hierarchies.
 * Simple hierarchies are hierarchies where a class is represented by a string.
 * The hierachy-structure is either added manualle or read from a file.
 */
public class SimpleHierarchyJDBMHTree {//extends AbstractSimpleHierarchy implements HierarchyThreaded {
//
//    /**
//     * JDBM RecordManager for containing information about the hierarchy
//     */
//    RecordManager recman;
//
//    /**
//     * JDBM HashTable for mapping from unique classIDs to class name
//     */
//    HTree idToName;
//
//    /**
//     * JDBM HashTable containing a Map from a class' name to its ID
//     */
//    HTree nameToID;
//
//    /**
//     * JDBM HashTable for mapping from a class' ID to a array containing the
//     * IDs of its superclasses
//     */
//    HTree superclassesTable;
//
//    /**
//     * Properties for the RecordManager <code>recman</code>
//     */
//    Properties props = new Properties();
//
//    /**
//     * key for looking up the <code>classCounter</code> in <code>recman</code>
//     */
//    long classCounterID;
//
//    /**
//     * Name of temporary JDBM-file used.
//     */
//    final String JDBMfilename;
//
//    /**
//     * Constructor.
//     * Constructs a new non-disjunctive hierarchy.
//     * @throws HierarchyPackage.HierarchyException Thrown if the hierarchy cannot be created.
//     */
//    public SimpleHierarchyJDBMHTree() throws HierarchyException {
//        this(false);
//    }
//
//    /**
//     * Constructor.
//     * Construct a new hierarchy.
//     * @param disjunctive Flag to tell whether or not the hierarchy should be disjunctive.
//     * @throws HierarchyPackage.HierarchyException Thrown if the hierarchy cannot be created.
//     */
//    public SimpleHierarchyJDBMHTree(boolean disjunctive) throws HierarchyException {
//
//        this.disjunctive = disjunctive;
//        top = new SimpleHClass(this, 0);
//        classCounter = 0;
//
//        String name;
//        try {
//
//            File hfile = File.createTempFile("SimpleHierarchy", "");
//            name = hfile.getName();
//            JDBMfilename = name;
//            hfile.delete();
//        } catch (IOException ex) {
//            throw new HierarchyException("Could not create new file " + ex.getMessage());
//        }
//
//        try {
//
//            //   RecordManagerOptions.
//            //recman = RecordManagerFactory.createRecordManager(name, props);
//            props.setProperty(RecordManagerOptions.DISABLE_TRANSACTIONS, "true");
//            //props.setProperty(RecordManagerOptions., "true");
////props.setProperty(RecordManagerOptions.CACHE_TYPE, RecordManagerOptions.NORMAL_CACHE);
//            //props.setProperty(RecordManagerOptions.CACHE_SIZE, "16384");
//            //props.setProperty(RecordManagerOptions.NORMAL_CACHE, "true");
//            recman = RecordManagerFactory.createRecordManager(name, props);
//            //BaseRecordManager base = RecordManagerFactory.createRecordManager(name);
//            ////BaseRecordManager base = new BaseRecordManager(name);
//            ////base.disableTransactions();
//            ////recman = new CacheRecordManager(base, new MRU(1024)); // 1048576
//
//            // Create idToName hash-table and add TOP as element;
//            idToName = HTree.createInstance(recman);
//            recman.setNamedObject("idToName", idToName.getRecid());
//            idToName.put(classCounter, "TOP");
//
//            // Create idToName hash-table and add TOP as element;
//            nameToID = HTree.createInstance(recman);
//            recman.setNamedObject("nameToID", nameToID.getRecid());
//            nameToID.put("TOP", classCounter);
//
//            //// Create superclassTable and add empty array as parents to TOP.
//            superclassesTable = HTree.createInstance(recman);
//            recman.setNamedObject("superclassesTable", superclassesTable.getRecid());
//            //long[] superclasses = new long[0];
//            //superclassesTable.put(classCounter, superclasses);
//
//            // Add classCounter to record manager
//            classCounterID = recman.insert(classCounter);
//            recman.setNamedObject("classCounter", classCounterID);
//
//            classCounter++;
//
//            recman.update(classCounterID, classCounter);
//            recman.commit();
//        } catch (IOException ex) {
//            throw new HierarchyException("JDBM IOException" + ex.getMessage());
//        }
//
//
//
//    }
//
//    /**
//     * Constructor.
//     * Create a hierarchy and load its structure from file.
//     * File has the following format;<br>
//     * * First line indicates hierarchy type, for instance:<br>
//     * <code>Tree-hierarchy</code><br>
//     * * Second line tells whether the hierarchy is disjunctive:<br>
//     * <code>non-disjunctive</code>
//     * * Following lines contains the hierarchy itself:<br>
//     *     * <code> subclass: superclass </code>
//     * @param name Name for the file containing the hierarchy-structure.
//     * @throws HierarchyPackage.HierarchyException Thrown if the hierarchy cannot be created.
//     */
//    public SimpleHierarchyJDBMHTree(String name) throws HierarchyException {
//        this();
//        try {
//            load2(name);
//        } catch (IOException ex) {
//            ex.printStackTrace();
//            throw new HierarchyException("Could not load hierarchy " + ex.getMessage());
//        }
//
//    }
//
//    /**
//     * Finalizer.
//     * Removes JDBM-files used.
//     * Notice that this method is not neceserali invoked by the garbage-collector before the programs exits if it is important to get the files deleted it should be called manually.
//     */
//    @Override
//    public void finalize() {
//        try {
//            File jdbmfile = new File(JDBMfilename + ".lg");
//            jdbmfile.delete();
//            jdbmfile = new File(JDBMfilename + ".db");
//            jdbmfile.delete();
//        } finally {
//        }
//    }
//
////
////    /**
////     * Loads an existing hierarchy from JDBM-file
////     * This method is called from the constructor when an existing hierarchy
////     * should be loaded
////     * @param name name of hierarchy to create
////     * @throws HierarchyPackage.HierarchyException Exception caused by problems with loading or creating hierarchy.
////     */
////    private void LoadSimpleHierarchy(String name) throws HierarchyException{
////
////        File JDBMfile = new File(name+ ".db");
////        if (JDBMfile.exists()) {
////            try {
////
////                recman = RecordManagerFactory.createRecordManager(name, props);
////                long recid;
////
////                // Get ID for idToName HashTable and load it
////                recid = recman.getNamedObject("idToName");
////                idToName = HTree.load(recman, recid);
////
////                // Get ID for nameToID HashTable and load it
////                recid = recman.getNamedObject("nameToID");
////                nameToID = HTree.load(recman, recid);
////
////                ///        in = new HashMap<String,Long>();
////                ///        FastIterator iter = nameToID.keys();
////                ///        String n = (String) iter.next();
////                ///        while ( n != null ) {
////                ///            in.put(n, (Long) nameToID.get(n));
////                ///            n = (String) iter.next();
////                ///        }
////
////
////                // Get ID for superclassesTable HashTable and load it
////                recid = recman.getNamedObject("superclassesTable");
////                superclassesTable = HTree.load(recman, recid);
////
////                // Get ID for classCounter, save it and load classCounter
////                classCounterID = recman.getNamedObject("classCounter");
////                classCounter= (Long) recman.fetch(classCounterID);
////
////            } catch (IOException ex) {
////                throw new HierarchyException("JDBM IOException" + ex.getMessage());
////            }
////        } else {
////            throw new HierarchyException("The hierarchy " + name + " does not exists");
////        }
////    }
//    @Override
//    String getName(int classID) throws HierarchyException {
//
//        if (classExists(classID)) {
//            try {
//
//                return (String) idToName.get(classID);
//            } catch (IOException ex) {
//                throw new HierarchyException("JDBM IOException" + ex.getMessage());
//            }
//        } else {
//            throw new HierarchyException("Class with ID: " + classID + " does not exist.");
//        }
//    }
//
//    @Override
//    synchronized int getID(String className) throws HierarchyException {
//
//        if (classExists(className)) {
//            try {
//                return (Integer) nameToID.get(className);
//            } catch (IOException ex) {
//                throw new HierarchyException("JDBM IOException" + ex.getMessage());
//            }
//        } else {
//            throw new HierarchyException("Class with name: " + className + " does not exist");
//        }
//    }
//
//    @Override
//    void addSuperclass(int superclassID, int classID) throws HierarchyException {
//
//        //System.err.println("addSuperclass(long,long). superclassID: " + superclassID + "  classID:" + classID);
//
//        if (classExists(superclassID) && classExists(classID)) {
//
//            // Do not add TOP in list of superclasses
//            if (superclassID != 0) {
//                try {
//
//                    // Retrieve existing superclasses
//                    // If we use getSuperclasses and classID currently has no
//                    // superclasses we will receive an arary containing 0 (TOP)
//                    // this is unpractical and therefore we acces the table directly
//                    long[] superclasses = (long[]) superclassesTable.get(classID);
//
//                    // In case no subclasses exists make empty array
//
//                    if (superclasses == null) {
//                        superclasses = new long[0];
//                    }
//
//                    // Create new array for superclasses
//                    long[] newSuperclasses = new long[superclasses.length + 1];
//                    System.arraycopy(superclasses, 0, newSuperclasses, 0, superclasses.length);
//
//                    // add new class in superclass array and save in table
//                    newSuperclasses[newSuperclasses.length - 1] = superclassID;
//                    superclassesTable.put(classID, newSuperclasses);
//
//                    recman.update(classCounterID, classCounter);
//                    recman.commit();
//                } catch (IOException ex) {
//                    throw new HierarchyException("JDBM IOException" + ex.getMessage());
//                }
//            }
//        } else {
//            throw new HierarchyException("Class with ID: " + superclassID + " or " + classID + " does not exist");
//        }
//    }
//
//    @Override
//    synchronized boolean classExists(int classID) throws HierarchyException {
//        try {
//            if (idToName.get(classID) != null) {
//                return true;
//            } else {
//                return false;
//            }
//        } catch (IOException ex) {
//            throw new HierarchyException("JDBM IOException" + ex.getMessage());
//        }
//    }
//
//    @Override
//    synchronized boolean classExists(String className) throws HierarchyException {
//        try {
//            if (nameToID.get(className) != null) {
//                return true;
//            } else {
//                return false;
//            }
//        } catch (IOException ex) {
//            throw new HierarchyException("JDBM IOException" + ex.getMessage());
//        }
//    }
//
//    @Override
//    int addClass(String className, int[] superclasses) throws HierarchyException {
//
//        int classID;
//        if (classExists(className)) {
//            classID = getID(className);
//        } else {
//            // Add new class to list of classes
//            classID = classCounter;
//            classCounter++;
//            try {
//                idToName.put(classID, className);
//                nameToID.put(className, classID);
//            } catch (IOException ex) {
//                throw new HierarchyException("JDBM IOException" + ex.getMessage());
//            }
//        }
//
//        for (int sc : superclasses) {
//            addSuperclass(sc, classID);
//        }
//
//        try {
//            recman.update(classCounterID, classCounter);
//            recman.commit();
//        } catch (IOException ex) {
//            ex.printStackTrace();
//        }
//
//        return classID;
//    }
//
//    @Override
//    synchronized int[] getSuperclasses(int classID) throws HierarchyException {
//
//        if (classExists(classID)) {
//            try {
//                int[] superclasses = (int[]) superclassesTable.get(classID);
//                if (superclasses == null) {
//                    if (classID == 0) {
//                        return new int[0];
//                    } else {
//                        int[] TOParray = {0};
//                        return TOParray;
//                    }
//                } else {
//                    return superclasses;
//                }
//            } catch (IOException ex) {
//                throw new HierarchyException("JDBM IOException" + ex.getMessage());
//            }
//        } else {
//            throw new HierarchyException("Class with ID: " + classID + " does not exist.");
//        }
//    }
//
//    @Override
//    int[] getAllClasses() throws HierarchyException {
//
//        List<Integer> IntegerClasses = new ArrayList<Integer>();
//        try {
//
//            FastIterator iter = idToName.keys();
//            Integer ID = (Integer) iter.next();
//            while (ID != null) {
//                IntegerClasses.add(ID);
//                ID = (Integer) iter.next();
//            }
//
//            Integer[] IntegerArray = IntegerClasses.toArray(new Integer[0]);
//            int[] classes = new int[IntegerArray.length];
//
//            for (int i = 0; i < IntegerArray.length; i++) {
//                classes[i] = IntegerArray[i];
//            }
//
//            int[] onlyTOP = {0};
//            if (Arrays.equals(classes, onlyTOP)) {
//                return new int[0];
//            } else {
//                return classes;
//            }
//
//        } catch (IOException ex) {
//            throw new HierarchyException("JDBM IOException" + ex.getMessage());
//        }
//    }
//
//    @Override
//    public ClassifiedDataSet getClassifications(Collection<Integer> dids, View v, HClass topClass,
//            int maxDepth, int minCount, int cutFraction, boolean saveData, ExecutorService pool) throws HierarchyException {
// throw new UnsupportedOperationException("Threaded is no longer supported becuase we do not have the split operation any more - simply implemt slit on the collection");
////        /**
////         * @TODO minCount currently not in use
////         */
////        ClassifiedDataSetStorage result = new ClassifiedDataSetStorage();
////
////        if ((topClass instanceof SimpleHClass) && (v instanceof SimpleView)) {
////
////            SimpleHClass tC = (SimpleHClass) topClass;
////            SimpleView dv = (SimpleView) v;
////
////            int maxThreads = 8;
////            DataIDs[] dd = dids.Split(maxThreads);
////
////            Future[] ff = new Future[maxThreads];
////            Set<Integer> running = new HashSet<Integer>();
////
////            for (int i = 0; i < maxThreads; i++) {
////
////                ff[i] = pool.submit(new SimpleThread(dd[i], dv, tC, maxDepth, result));
////                running.add(i);
////            }
////
////            while (!running.isEmpty()) {
////                try {
////                    Thread.sleep(100);
////                } catch (InterruptedException ex) {
////                    ex.printStackTrace();
////                }
////                for (int i = 0; i < maxThreads; i++) {
////                    if (ff[i].isDone()) {
////                        running.remove(i);
////                    }
////                }
////            }
////
////        }
////        return result;
//    }
//
//    @Override
//    public Map<HClass, Integer> saveEst(String filename, Set<HClass> classes) throws IOException {
//        throw new UnsupportedOperationException("Not supported yet.");
//    }
//
//    @Override
//    public Map<Integer, HClass> loadEst(String filename, Set<Integer> classIDs) throws IOException {
//        throw new UnsupportedOperationException("Not supported yet.");
//    }
//
//    @Override
//    public HClass newClass(Integer did, View v) {
//        throw new UnsupportedOperationException("Not supported yet.");
//    }
}
